package com.heima.article.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleCollectionMapper;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ArticleContentMapper;
import com.heima.article.mapper.ArticleMapper;
import com.heima.article.service.ArticleFreemarkerService;
import com.heima.article.service.ArticleService;
import com.heima.model.article.dtos.ArticleBehaviorDto;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.article.dtos.ArticleHomeDto;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleCollection;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.article.dtos.ArticleCollectionDto;
import com.heima.model.user.dtos.ReadDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.ApThreadLocalUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * @author ybw
 * @version 1.0
 * @date 2021/12/11 21:16
 */
@Service
@Slf4j
@Transactional
public class ArticleImpl extends ServiceImpl<ArticleMapper, ApArticle> implements ArticleService {
  @Autowired private ArticleMapper articleMapper;
  @Autowired private ApArticleConfigMapper apArticleConfigMapper;
  @Autowired private ArticleContentMapper articleContentMapper;
  @Autowired private ArticleFreemarkerService articleFreemarkerService;
  @Autowired private ApArticleCollectionMapper apArticleCollectionMapper;
  @Autowired private RedisTemplate<String, String> redisTemplate;
  /**
   * 文章列表
   *
   * @param type 1 上拉 ， 2 下拉
   * @param articleHomeDto
   * @return
   */
  @Override
  public ResponseResult loadList(Short type, ArticleHomeDto articleHomeDto) {
    // 校验参数
    if (articleHomeDto == null) {
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
    }
    List<ApArticle> articleList = articleMapper.loadList(type, articleHomeDto);
    return ResponseResult.okResult(articleList);
  }

  /**
   * 文章保存
   *
   * @param articleDto
   * @return
   */
  @Override
  public ResponseResult saveArticle(ArticleDto articleDto) {
    // 参数校验
    if (ObjectUtils.isEmpty(articleDto)) {
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    ApArticle apArticle = null;

    if (articleDto.getId() == null) {
      // 新增
      apArticle = new ApArticle();
      // 属性拷贝
      BeanUtils.copyProperties(articleDto, apArticle);
      // 保存文章表
      articleMapper.insert(apArticle);
      // 保存文章配置表
      ApArticleConfig articleConfig = new ApArticleConfig(apArticle.getId());
      apArticleConfigMapper.insert(articleConfig);
      // 保存文章内容表
      ApArticleContent apArticleContent = new ApArticleContent();
      apArticleContent.setArticleId(apArticle.getId());
      apArticleContent.setContent(articleDto.getContent());
      articleContentMapper.insert(apArticleContent);
    } else {
      // 修改
      // 根据id查询文章内容
      apArticle = articleMapper.selectById(articleDto.getId());
      if (ObjectUtils.isEmpty(apArticle)) {
        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
      }
      // 属性拷贝
      BeanUtils.copyProperties(articleDto, apArticle);
      // 修改文章信息表
      articleMapper.updateById(apArticle);
      // 修改文章内容表
      LambdaQueryWrapper<ApArticleContent> qw = new LambdaQueryWrapper<>();
      qw.eq(ApArticleContent::getArticleId, articleDto.getId());
      ApArticleContent apArticleContent = articleContentMapper.selectOne(qw);
      apArticleContent.setContent(articleDto.getContent());
      articleContentMapper.updateById(apArticleContent);
    }
    // 异步调用，生成静态模板
    articleFreemarkerService.saveOrUpdate(apArticle, articleDto.getContent());

    return ResponseResult.okResult(apArticle == null ? "" : apArticle.getId());
  }

  /**
   * 收藏文章
   *
   * @param dto
   * @return
   */
  @Override
  public ResponseResult articleCollection(ArticleCollectionDto dto) {
    // 参数校验
    if (ObjectUtils.isEmpty(dto)) {
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    // 获取登录用户
    ApUser loginUser = ApThreadLocalUtil.getUser();
    // 获取操作类型
    Short operation = dto.getOperation();
    // 获取文章id
    Long articleId = dto.getEntryId();
    // 根据文章id查询文章信息
    ApArticle apArticle = articleMapper.selectById(articleId);
    if (ObjectUtils.isEmpty(apArticle)) {
      return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
    }
    if (operation == 0) {
      // 收藏
      ApArticleCollection articleCollection = new ApArticleCollection();
      articleCollection.setEntryId(loginUser.getId());
      articleCollection.setCollectionTime(new Date());
      articleCollection.setArticleId(dto.getEntryId());
      articleCollection.setType(dto.getType());
      articleCollection.setPublishedTime(apArticle.getPublishTime());
      apArticleCollectionMapper.insert(articleCollection);
      // 存储到redis中
      redisTemplate
          .opsForHash()
          .put(
              "USER_BEHAVIOR:COLLECTION:" + loginUser.getId(),
              dto.getEntryId().toString(),
              dto.getType().toString());
    } else if (operation == 1) {
      // 取消收藏
      LambdaQueryWrapper<ApArticleCollection> qw = new LambdaQueryWrapper<>();
      qw.eq(ApArticleCollection::getEntryId, loginUser.getId())
          .eq(ApArticleCollection::getArticleId, dto.getEntryId());
      apArticleCollectionMapper.delete(qw);
      // 取消收藏
      redisTemplate
          .opsForHash()
          .delete(
              "USER_BEHAVIOR:COLLECTION:" + loginUser.getId(),
              dto.getEntryId().toString(),
              dto.getType().toString());
    }
    return ResponseResult.okResult(null);
  }

  /**
   * 加载文章行为
   *
   * @param dto
   * @return
   */
  @Override
  public ResponseResult loadArticleBehavior(ArticleBehaviorDto dto) {
    // 参数校验
    if (ObjectUtils.isEmpty(dto)) {
      return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
    }
    // 获取参数
    Long articleId = dto.getArticleId();
    Integer authorId = dto.getAuthorId();
    // 获取用户id
    Integer loginUserId = ApThreadLocalUtil.getUser().getId();
    // 查询redis
    HashOperations<String, Object, Object> ops = redisTemplate.opsForHash();
    Boolean likeFlag =
        ops.hasKey(
            "USER_BEHAVIOR:LIKE:" + loginUserId + ":" + articleId.toString(), String.valueOf(0));
    Boolean unlikeFlag = ops.hasKey("USER_BEHAVIOR:UNLIKE:" + loginUserId, articleId.toString());
    Boolean collectionFlag =
        ops.hasKey("USER_BEHAVIOR:COLLECTION:" + loginUserId, articleId.toString());
    Boolean followFlag = ops.hasKey("USER_BEHAVIOR:FOLLOW:" + loginUserId, authorId.toString());

    // 封装返回值对象
    HashMap<String, Boolean> map = new HashMap<>();
    map.put("islike", likeFlag);
    map.put("isunlike", unlikeFlag);
    map.put("iscollection", collectionFlag);
    map.put("isfollow", followFlag);

    return ResponseResult.okResult(map);
  }
}
